import set from 'lodash/set';
import url from 'url';
import mongoose from 'mongoose';
import { gqcPermissionCheck } from '@kuiper/auth';
import errorCodesBuilder from '../helpers/errorCodesBuilder';
import escapeRegExp from '../helpers/escapeRegExp';

const errorCodes = errorCodesBuilder('更新任务失败');

export default server => {
	const {
		app: {
			schemaComposer,
			model: { Alert },
		},
	} = server;

	server.methods.registerGraphQLSchema({
		name: 'Alert',
		model: Alert,
		queryFields: {
			Count: 'count',
			Pagination: 'pagination',
		},
		mutationFields: {},
		onPreAddFields(tc) {
			const {
				app: {
					graphqlResolvers,
					schema: { Task, User, Job },
				},
				methods: { usernameSearchFilterArgQuery },
			} = server;

			tc.addRelation('task', {
				resolver: () => Task.mongooseResolvers.dataLoader({ lean: true }),
				prepareArgs: {
					_id: source => source.taskId || [],
				},
				projection: { taskId: 1 },
			});

			tc.addRelation('user', {
				resolver: () => User.mongooseResolvers.dataLoader({ lean: true }),
				prepareArgs: {
					_id: source => source.uid || [],
				},
				projection: { uid: 1 },
			});

			tc.addRelation('job', {
				resolver: () => Job.mongooseResolvers.dataLoader({ lean: true }),
				prepareArgs: {
					_id: source => source.jobId,
				},
				projection: { jobId: 1 },
			});

			// #region count
			graphqlResolvers.Query.AlertCount = graphqlResolvers.Query.AlertCount.addFilterArg(
				{
					name: 'createTimeGTE',
					type: 'Date',
					description: '创建时间大于等于',
					query: (query, value) => {
						const fieldName = 'createTime';
						let field = query[fieldName] || {};
						if (typeof field !== 'object') field = {};
						query[fieldName] = { ...field, $gte: value };
					},
				}
			)
				.addFilterArg({
					name: 'createTimeLTE',
					type: 'Date',
					description: '创建时间小于等于',
					query: (query, value) => {
						const fieldName = 'createTime';
						let field = query[fieldName] || {};
						if (typeof field !== 'object') field = {};
						query[fieldName] = { ...field, $lte: value };
					},
				})
				.addFilterArg({
					name: 'usernameSearch',
					type: 'String',
					description: '用户名搜索',
					query: usernameSearchFilterArgQuery,
				})
				.addFilterArg({
					name: 'targetSearch',
					type: 'String',
					description: 'target搜索',
					query: (query, value) => {
						query.target = {
							$regex: escapeRegExp(value.trim()),
							$options: 'i',
						};
					},
				})
				.withMiddlewares([
					gqcPermissionCheck({
						required: 'cloud-monitor\x01listAlert',
						selfOnlyArgsBuilder(
							_source,
							args,
							{
								request: {
									auth: {
										credentials: { uid },
									},
								},
							}
						) {
							set(args, ['filter', 'uid'], uid);
						},
					}),
				]);
			// #endregion

			// #region pagination
			graphqlResolvers.Query.AlertPagination = graphqlResolvers.Query.AlertPagination.addFilterArg(
				{
					name: 'createTimeGTE',
					type: 'Date',
					description: '创建时间大于等于',
					query: (query, value) => {
						const fieldName = 'createTime';
						let field = query[fieldName] || {};
						if (typeof field !== 'object') field = {};
						query[fieldName] = { ...field, $gte: value };
					},
				}
			)
				.addFilterArg({
					name: 'createTimeLTE',
					type: 'Date',
					description: '创建时间小于等于',
					query: (query, value) => {
						const fieldName = 'createTime';
						let field = query[fieldName] || {};
						if (typeof field !== 'object') field = {};
						query[fieldName] = { ...field, $lte: value };
					},
				})
				.addFilterArg({
					name: 'usernameSearch',
					type: 'String',
					description: '用户名搜索',
					query: usernameSearchFilterArgQuery,
				})
				.addFilterArg({
					name: 'targetSearch',
					type: 'String',
					description: '正则过滤: target',
					query: (query, value) => {
						query.target = {
							$regex: escapeRegExp(value.trim()),
							$options: 'i',
						};
					},
				})
				.addFilterArg({
					name: 'taskSettingsCollectType',
					type: 'String',
					description: '扫描方式: 增量/全量',
					query: (query, value) => {
						query['task.taskSetting.collect.type'] = value;
					},
				})
				.withMiddlewares([
					gqcPermissionCheck({
						required: 'cloud-monitor\x01listAlert',
						selfOnlyArgsBuilder(_source, args, { request }) {
							set(args, ['filter', 'uid'], request.auth.credentials.uid);
						},
					}),
				]);
			// #endregion
		},
	});

	schemaComposer.Query.addFields({
		AlertTodayTopAsset: {
			description: '更新资产',
			type: schemaComposer.createObjectTC(`
				type AlertTodayTopAssetResult {
					_id: String
					count: Int
					asset: String
					note: String
				}
			`),
			resolve: async (root, args, { request }) => {
				const {
					auth: {
						credentials: { uid },
					},
					server: {
						app: {
							model: { Alert, Job },
						},
					},
				} = request;

				let today = Date.now();
				today = new Date(today - (today % (24 * 60 * 60 * 1000)));

				let todayTopAlertAsset;
				try {
					todayTopAlertAsset = await Alert.aggregate([
						{
							$match: {
								uid: new mongoose.Types.ObjectId(uid),
								createTime: { $gte: today },
							},
						},
						{ $group: { _id: '$target', count: { $sum: 1 } } },
						{ $sort: { count: -1 } },
						{ $limit: 1 },
					]).exec();
					todayTopAlertAsset = (todayTopAlertAsset || [])[0];
				} catch (err) {
					const error = errorCodes['[0A]告警统计失败'].from(err);
					request.log.error({ error }, error.rawMessage);
					throw error;
				}

				let target = todayTopAlertAsset?._id || '';
				// 兼容脏数据 后期去掉
				const patt = /^https?:\/\//;
				if (!patt.test(target)) {
					target = `http://${target}`;
				}
				let host;
				try {
					host = new url.URL(target).host;
				} catch {}

				const job = await Job.findOne({
					uid,
					'target.host': host,
				})
					.exec()
					.catch(() => {});

				return {
					_id: `${new Date().toLocaleDateString()}-${uid}`,
					count: todayTopAlertAsset?.count,
					asset: todayTopAlertAsset?._id,
					note: job?.note,
				};
			},
		},
	});
};
